package DigiJoe;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.JFileChooser;

public class GuiController implements MouseListener,WindowListener {

    private GuiView guiView;
    private Main application;
    private boolean loaded = false;

    public GuiController(Main application) {
        this.application = application;
        
        //View példányosítása
        guiView = new GuiView(this);
        guiView.setSize(1000, 800);
        guiView.setLocation(10, 10);
        guiView.addWindowListener(this);
        guiView.setResizable(false);
        guiView.setVisible(true);
    }

    //Szimuláció léptetése
    public void StepSimulation() {
        try {
            //leptetes
            SimulationController.stepSimulation();
            UpdateView();
            guiView.SetStatus("Network stepped at " + new Date().toString());
        } catch (Exception ex) {
            guiView.displayDialog("Network is unstable!");
            guiView.SetStatus("Network is unstable at " + new Date().toString());
        }
    }

    //Hálózat resetelése
    public void ResetNetwork() {
        try {
            SimulationController.resetSimulation();
            UpdateView();
            guiView.SetStatus("Network reset at " + new Date().toString());
        } catch (Exception ex) {
            guiView.displayDialog("A problem occured with resetting the network!");
            guiView.SetStatus("Network reset failed at " + new Date().toString());
        }
    }

    private void initView()
    {
        //Komponensek átadása
        ArrayList<ElementType> components = new ArrayList<ElementType>();
        ArrayList<Integer> inPorts = new ArrayList<Integer>();
        ArrayList<Integer> outPorts = new ArrayList<Integer>();

        for (int i = 0; i < NetworkLoaderController.getElementsSize(); i++) {
            try {
                DigitalElement e = NetworkLoaderController.getDigitalElement(i);
                components.add(e.getType());
                outPorts.add(e.outputList.size());
                if(e.getType() == ElementType.Switch || e.getType() == ElementType.Generator){
                    inPorts.add(0);
                }
                else{
                    inPorts.add(((DigitalGate)e).inputList.size());
                }
            } catch (Exception e) {
            }
        }
        
        //build the wirelist
        ArrayList<Integer[]> wires = new ArrayList<Integer[]>();
        for(Wire w : NetworkController.getInstance().getWires()){
            wires.add(new Integer[]{
                NetworkLoaderController.getElementsId(w.GetOutElement()),
                w.getOutport(),
                NetworkLoaderController.getElementsId(w.GetInGate()),
                w.getInport()
            });
        }
        
        //View példányosítása
        guiView.initWithData(components, inPorts, outPorts, wires);
    }
    
    //Hálózat betöltése
    public void LoadNetwork() {
        File file = null;
        try {
            JFileChooser fc = new JFileChooser();
            fc.setAcceptAllFileFilterUsed(false);
            fc.addChoosableFileFilter(new XmlFilter());
            int returnVal = fc.showDialog(guiView, "Load Network");


            if (returnVal == JFileChooser.APPROVE_OPTION) {
                file = fc.getSelectedFile();
                //Open file
                NetworkLoaderController.loadNetworkFromXMLFile(file.getPath());
                
                //set loaded
                loaded = true;
                
                //init the view with data
                initView();
                
                //update the view
                UpdateView();
                guiView.SetStatus("Network loaded at " + new Date().toString());
            } else {
                throw new Exception();
            }
        } catch (Exception e) {
            if (file != null) {
                guiView.displayDialog("The network from " + file + " could not be loaded!");
                guiView.SetStatus("Network load failed at " + new Date().toString());
            } else {
                guiView.displayDialog("The network could not be loaded!");
                guiView.SetStatus("Network load failed at " + new Date().toString());
            }
        }
    }

    //Megfelelő switch kapcsolása
    public void StepSwitch(int id) {
        try {
            //kapcsolo elerese id alapjan
            Switch sw = (Switch) NetworkLoaderController.getDigitalElement(id);
            //kapcsolo allitasa
            sw.stepState();
            guiView.SetStatus("Switch " + id + "  stepped at " + new Date().toString());
        } catch (Exception ex) {
            guiView.SetStatus("Switch step failed at " + new Date().toString());
        }
    }

    //View Updateelése
    public void UpdateView(){
        //for each component image update the image
        for (int i = 0; i < NetworkLoaderController.getElementsSize(); i++) {
            try {
                //get the element from the loader
                DigitalElement e = NetworkLoaderController.getDigitalElement(i);
                switch (e.getType())
                {
                    //if it is a led
                    case Led:
                        Led led = (Led)e;
                        //change its state accordingly
                        if (led.getState() == Sign.High)
                        {
                            guiView.getComponentImage(i).setOnOff(true);
                        } else
                        {
                            guiView.getComponentImage(i).setOnOff(false);
                        }
                        break;
                    //if it is a switch
                    case Switch:
                        Switch swtch = (Switch)e;
                        //change its state accordingly
                        if (swtch.getState() == Sign.High)
                        {
                            guiView.getComponentImage(i).setOnOff(true);
                        } else
                        {
                            guiView.getComponentImage(i).setOnOff(false);
                        }
                        break;
                    default:
                        break;
                }
            } catch (Exception e) {
            }
        }
        
        //View rajzolja ki
        guiView.Draw();
    }

    //Egér kattintás kezelése
    @Override
    public void mouseClicked(MouseEvent e) {
        try {
            //Ha a kattintott komponens egy switch, akkor kapcsolás
            int id = guiView.GetClickedComponent(e.getX(), e.getY());
            //did we click on a switch
            if (NetworkLoaderController.getDigitalElement(id).getClass() == Switch.class) {
                //step the switch
                StepSwitch(id);
                //update the view
                UpdateView();
            }
        } catch (Exception ex) {
        }
    }

    //Kilépés a programból
    public void Exit() {
        System.exit(0);
    }

    //getter
    public boolean getLoaded()
    {
        return loaded;
    }
    //Interfész implementálása miatt kötelező függvények
    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void windowOpened(WindowEvent e) {
    }

    @Override
    public void windowClosing(WindowEvent e) {
        Exit();
    }

    @Override
    public void windowClosed(WindowEvent e) {
    }

    @Override
    public void windowIconified(WindowEvent e) {
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
    }

    @Override
    public void windowActivated(WindowEvent e) {
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
       
    }
}
